package cn.nexttec.noteplayer.ui.widget

import android.content.Context
import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.ColorDrawable
import android.os.Handler
import android.os.Looper
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.HorizontalScrollView
import android.widget.LinearLayout
import android.widget.PopupWindow
import android.widget.TextView
import cn.nexttec.noteplayer.R
import kotlin.math.abs

class ScrollSelectorPopup<T>(
    private val context: Context,
    private val anchorView: View,
    private val items: List<T>,
    private val displayMapper: (T) -> String,
    private val defaultItem: T,
    private val onItemSelected: (T) -> Unit
) {

    private var popupWindow: PopupWindow? = null
    private val handler = Handler(Looper.getMainLooper())
    private var dismissRunnable: Runnable? = null

    fun show() {
        val view = LayoutInflater.from(context).inflate(R.layout.popup_scroll_selector, null)
        val container = view.findViewById<LinearLayout>(R.id.item_container)
        val scrollView = view.findViewById<HorizontalScrollView>(R.id.scrollView)

        popupWindow = PopupWindow(view, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true).apply {
            isOutsideTouchable = true
            setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
            showAsDropDown(anchorView)
        }

        items.forEachIndexed { index, item ->
            val tv = TextView(context).apply {
                text = displayMapper(item)
                setPadding(24, 16, 24, 16)
                setTextSize(TypedValue.COMPLEX_UNIT_SP, 18f)
                setTextColor(if (item == defaultItem) Color.WHITE else Color.GRAY)
                setTypeface(null, if (item == defaultItem) Typeface.BOLD else Typeface.NORMAL)
            }
            container.addView(tv)
        }

        scrollView.setOnScrollChangeListener { _, _, _, _, _ ->
            resetDismissTimer(container, scrollView)
        }

        scrollToItem(container, scrollView, defaultItem)
        resetDismissTimer(container, scrollView)
    }

    private fun scrollToItem(container: LinearLayout, scrollView: HorizontalScrollView, item: T) {
        val index = items.indexOf(item).takeIf { it >= 0 } ?: 0
        scrollView.post {
            val child = container.getChildAt(index)
            val scrollTo = child.left + child.width / 2 - scrollView.width / 2
            scrollView.smoothScrollTo(scrollTo, 0)
        }
    }

    private fun resetDismissTimer(container: LinearLayout, scrollView: HorizontalScrollView) {
        dismissRunnable?.let { handler.removeCallbacks(it) }

        dismissRunnable = Runnable {
            val centerX = scrollView.scrollX + scrollView.width / 2
            var closestView: View? = null
            var minDistance = Int.MAX_VALUE
            var selectedItem: T = defaultItem

            for (i in 0 until container.childCount) {
                val child = container.getChildAt(i)
                val location = IntArray(2)
                child.getLocationOnScreen(location)
                val childCenter = location[0] + child.width / 2
                val distance = abs(centerX - childCenter)

                if (distance < minDistance) {
                    minDistance = distance
                    closestView = child
                    selectedItem = items[i]
                }
            }

            onItemSelected(selectedItem)
            popupWindow?.dismiss()
        }

        handler.postDelayed(dismissRunnable!!, 1000)
    }
}
